﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ReporterControlLibrary.Models;
using ReporterControlLibrary.UIHelpers;
using ReporterEngine;
using System.Collections.ObjectModel;
using System.Linq;

namespace ReporterControlLibrary
{
    /// <summary>
    /// Interaction logic for EvaluatePathToolbox.xaml
    /// </summary>
    public partial class EvaluatePathToolbox : UserControl, INotifyPropertyChanged
    {
        private ObservableCollection<string> _selectedFilterTypes = new ObservableCollection<string>();
        private ObservableCollection<string> _selectedProperties = new ObservableCollection<string>();
        private ObservableCollection<string> _selectedReferences = new ObservableCollection<string>();
        private ObservableCollection<string> _selectedUseBys = new ObservableCollection<string>();
        private Project _project;

        public Project Project
        {
            get
            {
                if (DataContext != null && DataContext is MetaModel)
                {
                    _project = (DataContext as MetaModel).Project;
                    return _project;
                }
                return null;
            }
        }

        public ObservableCollection<string> SelectedFilterTypes
        {
            get { return _selectedFilterTypes; }
            set { _selectedFilterTypes = value; }
        }

        public ObservableCollection<string> SelectedProperties
        {
            get { return _selectedProperties; }
            set { _selectedProperties = value; }
        }

        public ObservableCollection<string> SelectedReferences
        {
            get { return _selectedReferences; }
            set { _selectedReferences = value; }
        }

        public ObservableCollection<string> SelectedUseBys
        {
            get { return _selectedUseBys; }
            set { _selectedUseBys = value; }
        }

        public EvaluatePathToolbox()
        {
            this.InitializeComponent();
            DataContextChanged += new DependencyPropertyChangedEventHandler(EvaluatePathToolboxDataContextChanged);
            david.EvalDocasny += new EventHandler(david_EvalDocasny);
        }

        void david_EvalDocasny(object sender, EventArgs e)
        {
            ClearCollections();
        }

        void EvaluatePathToolboxDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            ClearCollections();
        }

        // TODO: presunut funkcionalitu na binding a triggers
        private void MethodListBoxItemMouseMove(object sender, MouseEventArgs e)
        {
            MethodDescription.Text = (((sender as FrameworkElement).DataContext) as ModelMethod).Description;
        }
        
        private void StoredExpressionListBoxItemMouseMove(object sender, MouseEventArgs e)
        {
            StoredExpressionDescription.Text = (((sender as FrameworkElement).DataContext) as ModelStoredExpression).Description;
        }
       
        // list button click handlers - group of checked values
        private void ApplyPropertiesClick(object sender, RoutedEventArgs e)
        {
            Project.MetaModel.EvalExpression += " >> " + string.Join(", ", SelectedProperties);
            david.Eval(Project);
        }

        private void ApplyReferencesClick(object sender, RoutedEventArgs e)
        {
            Project.MetaModel.EvalExpression += " >> " + string.Join(", ", SelectedReferences);
            david.Eval(Project);
        }

        private void ApplyUsedBysClick(object sender, RoutedEventArgs e)
        {
            Project.MetaModel.EvalExpression += " << " + string.Join(", ", SelectedUseBys);
            david.Eval(Project);
        }

        private void ApplyFilterTypesClick(object sender, RoutedEventArgs e)
        {
            Project.MetaModel.EvalExpression += " >> (" + string.Join(", ", SelectedFilterTypes.Select(x => "'" + x + "'")) + ")";
            david.Eval(Project);
        }

        private void RefreshStoredExpression(object sender, RoutedEventArgs e)
        {
            Project.MetaModel.EvalExpression += " >> " + string.Join(", ", SelectedFilterTypes);
            david.Eval(Project);
        }

        // single list items's button click handlers 
        private void ApplyPropertyClick(object sender, RoutedEventArgs e)
        {
            var modelProperty = (sender as FrameworkElement).DataContext as ModelProperty;

            if (modelProperty != null)
            {
                // Project
                Project.MetaModel.EvalExpression += " >> " + modelProperty.Name;
                david.Eval(Project);
            }
        }

        private void ApplyReferenceClick(object sender, RoutedEventArgs e)
        {
            var modelReference = (sender as FrameworkElement).DataContext as ModelReference;

            if (modelReference != null)
            {
                // Project
                Project.MetaModel.EvalExpression += " >> " + modelReference.Name;
                david.Eval(Project);
            }
        }

        private void ApplyUsedByClick(object sender, RoutedEventArgs e)
        {
            var modelUsedBy = (sender as FrameworkElement).DataContext as ModelUsedBy;

            if (modelUsedBy != null)
            {
                // Project
                Project.MetaModel.EvalExpression += " << " + modelUsedBy.Name;
                david.Eval(Project);
            }
        }

        private void ApplyFilterTypeClick(object sender, RoutedEventArgs e)
        {
            var modelType = (sender as FrameworkElement).DataContext as ModelType;

            if (modelType != null)
            {
                Project.MetaModel.EvalExpression += " >> ('" + modelType.Name + "')";
                david.Eval(Project);
            }
        }

        private void ApplyMethodClick(object sender, RoutedEventArgs e)
        {
            var modelMethod = (sender as FrameworkElement).DataContext as ModelMethod;

            if (modelMethod != null)
            {
                Project.MetaModel.EvalExpression += " >> " + modelMethod.Name + "()";
                david.Eval(Project);
            }
        }

        private void ApplyStoredExpressionClick(object sender, RoutedEventArgs e)
        {
            var modelSE = (sender as FrameworkElement).DataContext as ModelStoredExpression;

            if (modelSE != null)
            {
                Project.MetaModel.EvalExpression = modelSE.Name;
                david.Eval(Project);
            }
        }

        // single list items's check handlers 
        private void PropertyCheckBoxChecked(object sender, RoutedEventArgs e)
        {
            var item = (sender as FrameworkElement).DataContext as ModelProperty;

            if (item != null)
            {
                AddItemToList(SelectedProperties, item.Name);
            }

        }

        private void PropertyCheckBoxUnchecked(object sender, RoutedEventArgs e)
        {
            var item = (sender as FrameworkElement).DataContext as ModelProperty;

            if (item != null)
            {
                RemoveItemFromList(SelectedProperties, item.Name);
            }
        }

        private void ReferenceCheckBoxChecked(object sender, RoutedEventArgs e)
        {
            var item = (sender as FrameworkElement).DataContext as ModelReference;

            if (item != null)
            {
                AddItemToList(SelectedReferences, item.Name);
            }
        }

        private void ReferenceCheckBoxUnchecked(object sender, RoutedEventArgs e)
        {
            var item = (sender as FrameworkElement).DataContext as ModelReference;

            if (item != null)
            {
                RemoveItemFromList(SelectedReferences, item.Name);
            }
        }
        private void UsedByCheckBoxChecked(object sender, RoutedEventArgs e)
        {
            var item = (sender as FrameworkElement).DataContext as ModelUsedBy;

            if (item != null)
            {
                AddItemToList(SelectedUseBys, item.Name);
            }
        }

        private void UsedByCheckBoxUnchecked(object sender, RoutedEventArgs e)
        {
            var item = (sender as FrameworkElement).DataContext as ModelUsedBy;

            if (item != null)
            {
                RemoveItemFromList(SelectedUseBys, item.Name);
            }
        }

        private void FilterTypeCheckBoxChecked(object sender, RoutedEventArgs e)
        {
            var item = (sender as FrameworkElement).DataContext as ModelType;

            if (item != null)
            {
                AddItemToList(SelectedFilterTypes, item.Name);
                ApplyFilterTypesBtn.IsEnabled = (SelectedFilterTypes.Count == 0) ? false : true;
            }
        }

        private void FilterTypeCheckBoxUnchecked(object sender, RoutedEventArgs e)
        {
            var item = (sender as FrameworkElement).DataContext as ModelType;

            if (item != null)
            {
                RemoveItemFromList(SelectedFilterTypes, item.Name);
                ApplyFilterTypesBtn.IsEnabled = (SelectedFilterTypes.Count == 0) ? false : true;
            }
        }

        // helper methods
        private static void AddItemToList(ObservableCollection<string> list, string item)
        {
            if (list != null && !String.IsNullOrEmpty(item) && !list.Contains(item))
            {
                list.Add(item);
            }
        }
        private static void RemoveItemFromList(ObservableCollection<string> list, string item)
        {
            if (list != null && !String.IsNullOrEmpty(item) && list.Contains(item))
            {
                list.Remove(item);
            }
        }

        private void ClearCollections()
        {
            SelectedProperties.Clear();
            SelectedReferences.Clear();
            SelectedUseBys.Clear();
            SelectedFilterTypes.Clear();
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected void NotifyPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

    }
}